#ifndef X86_MEMPOOL_H
#define X86_MEMPOOL_H

#include <lib/type.h>
#include <lib/list.h>
#include <os/memcache.h>

#define MEM_POOL_SIZE 128

// mem range index
#define MEM_RANGE_DMA 0
#define MEM_RANGE_KERNEL 1
#define MEM_RANGE_USER 2

// mem range index count
#define MEM_RANGE_COUNT 3

// node size
#define MEM_NODE_SIZE (sizeof(mem_node_t))

// section count
#define MEM_SECTION_MAX 12

// section size
#define MEM_SECTION_SIZE_MAX 2048 // 8 MB

#define MEM_NODE_SECTION_SET(node) (node->section = (section))

// mem section block
typedef struct mem_section
{
    list_t free_list_head;
    uint32_t nodecount;
    uint32_t sectionsize;
} mem_section_t;

// mem node struct
typedef struct mem_node
{
    uint8_t ref;            // reference
    uint8_t flags;          // node flags
    uint32_t count;         // node page count
    uint32_t size;          // node size
    uint32_t usedcount;     // reference count
    mem_cache_t *mem_cache; // mem cache point
    mem_group_t *mem_group; // mem_group point
    list_t list;            // node list
    mem_section_t *section; // section point
} mem_node_t;

typedef struct mem_range
{
    uint32_t startbase;                     // start base
    uint32_t endbase;                       // end base
    uint32_t size;                          // size
    uint32_t pages;                         // page count
    mem_node_t *nodetable;                  // node table point
    mem_section_t section[MEM_SECTION_MAX]; // section
} mem_range_t;

int MemRangeInit(uint8_t index, uint32_t start, uint32_t end);
int MemSectionInit(mem_section_t *section, uint32_t size);
void MemSectionSet(mem_section_t *section, uint32_t nodecount, uint32_t size);
void MemNodeInit(mem_node_t *node, uint32_t ref, uint32_t size);
mem_range_t *GetMemRangeByNode(mem_node_t *node);
mem_node_t *Pybase2Memnode(uint32_t pybase);
uint32_t Memnode2Pybase(mem_node_t *node);
mem_range_t *GetMemRangeByPybase(uint32_t pybase);
void *AllocMemNode(uint8_t range_index, uint32_t count);
int FreeMemNode(uint32_t pybase);
uint32_t _GetFreePageCountOnRange(uint32_t index);
uint32_t _GetFreePageCount();
void MemPoolDump();

#define MemGetFreeSize() (_GetFreePageCount() * PAGE_SIZE)
#endif